package net.riking.report.simu.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import net.riking.mbtq.common.AESOperator;
import net.riking.mbtq.common.StringUtil;
import net.riking.mbtq.common.SystemConfigUtil;
import net.riking.mbtq.config.Const;
import net.riking.mbtq.dao.PbocUserPwdRepo;
import net.riking.mbtq.entity.model.PasswordModifPojo;
import net.riking.mbtq.entity.model.PbocUserInfo;
import net.riking.mbtq.entity.model.PbocUserPwd;
import net.riking.mbtq.service.PbocPwdHistoryService;
import net.riking.mbtq.signature.SignatureService;
import net.riking.mbtq.vo.PbocPwdParam;
import net.riking.report.simu.HttpConnectUtil;
import net.riking.report.simu.SimuLoginParam;
import net.riking.report.simu.SimuLoginService;
import net.sf.json.JSONObject;

/**
 * 
 */
@Service(value = "oldSimuLoginService")
public class OldSimuLoginServiceImpl implements SimuLoginService {
	private static Logger logger = LogManager.getLogger(OldSimuLoginServiceImpl.class);

	// 人行环境
	@Value("${pbc.environment}")
	private String pbcEnvironment = "test";

	@Autowired
	private SignatureService signatureService;

	/**
	 * 获取当前登录用户信息
	 */
	private String getCurrUserInfoUrl = "/v2/{environment}/web-bank-manage/userDetail/getUserInfoDetailByHref.action";

	@Autowired
	private PbocUserPwdRepo pbocUserPwdRepo;

	@Autowired
	PbocPwdHistoryService pbocPwdHistoryService;

	@Autowired
	private SystemConfigUtil systemConfigUtil;

	@Autowired
	private AESOperator aesOperator;

	@Override
	public Logger getLogger() {
		return logger;
	}

	@Override
	public String getCookie(SimuLoginParam simuLoginParam) throws Exception {
		String cookie = "";
		logger.info("-------模拟登陆开始：获取cookie-----------");
		cookie = doPost(translateSimuLoginParam(simuLoginParam), "UTF-8",
				changeByLoginUrl(simuLoginParam.getLoginUrl(), simuLoginParam.getLoginPostUrl()));
		if (StringUtils.isBlank(cookie)) {
			cookie = null;
			logger.error("获取cookie失败！！！" + cookie);
			// throw new RuntimeException("获取cookie失败！！！");
		}
		logger.info("获取到cookie:" + cookie);
		return cookie;
	}

	@Override
	public Map<String, String> translateSimuLoginParam(SimuLoginParam simuLoginParam) {
		Map<String, String> param = new LinkedHashMap<>();
		if (signatureService.isUserSign()) {
			try {
				String signinfo = signatureService.sign(simuLoginParam.getUserName(), simuLoginParam);
				param.put("signinfo", signinfo);
			} catch (Exception e) {
				e.printStackTrace();
				logger.info("登入获取签名失败");
				throw new RuntimeException("加密失败");
			}
		}
		param.put("username", simuLoginParam.getUserName());
		// AESOperator.getInstance().decrypt("wdd888!111"));
		param.put("password", simuLoginParam.getEncryptPassword());
		param.put("local_network", simuLoginParam.getLocalNetwork());
		param.put("local_disk", simuLoginParam.getLocalDisk());
		param.put("local_cpu", simuLoginParam.getLocalCpu());
		logger.info("【password】:" + simuLoginParam.getEncryptPassword());
		logger.info("【local_network】:" + simuLoginParam.getLocalNetwork());
		logger.info("【local_disk】:" + simuLoginParam.getLocalDisk());
		logger.info("【local_cpu】:" + simuLoginParam.getLocalCpu());
		if (signatureService.isUserSign()) {
			try {
				String signinfo = signatureService.sign(simuLoginParam.getUserName(), simuLoginParam);
				logger.info("【signinfo】:" + signinfo);
			} catch (Exception e) {
				e.printStackTrace();
				logger.info("登入获取签名失败");
				throw new RuntimeException("加密失败");
			}
		}
		logger.info("-------拼接post登陆请求参数成功,USERNAME:" + simuLoginParam.getUserName());
		return param;
	}

	/**
	 * 修改人行用户密码
	 * 
	 * @param params
	 * @param cookie
	 */
	@Override
	public PbocUserPwd updatePbocUserPassword(PbocUserInfo pbocUserInfo) throws Exception {

		String loginUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.LOGON_QUERY_DIR);

		String loginPostUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.LOGINURL);

		String tokenUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.TOKENURL);

		String loginSandNumUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.LOGINSANDNUMURL);

		String updatePasswordUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(),
				Const.UPDATEPASSWORDURL);

		if (StringUtils.isBlank(loginUrl) || StringUtils.isBlank(updatePasswordUrl)) {
			logger.error("征信登录地址为空或密码修改请求地址为空，请检查！");
			// 保存密码更新历史
			throw new RuntimeException("征信登录地址为空或密码修改请求地址为空");
		}

		SimuLoginParam simuLoginParam = new SimuLoginParam(pbocUserInfo);
		simuLoginParam.setLoginUrl(loginUrl);
		simuLoginParam.setLoginPostUrl(loginPostUrl);

		simuLoginParam.setLoginSandNumUrl(loginSandNumUrl);
		simuLoginParam.setTokenUrl(tokenUrl);
		simuLoginParam.setUpdatePasswordUrl(updatePasswordUrl);

		// 获取cookie
		String cookie = this.getCookie(simuLoginParam);
		if (StringUtils.isBlank(cookie)) {
			logger.error("获取cookie失败");
			throw new RuntimeException("获取cookie失败");
		}
		// 获取token
		String token = this.getToken(simuLoginParam, cookie);
		if (StringUtils.isBlank(token)) {
			logger.error("获取token失败");
			throw new RuntimeException("获取token失败");
		}

		// 获取所有密码
		List<PbocUserPwd> allPwdList = pbocUserPwdRepo.getAllBySts();

		if (null == allPwdList || allPwdList.isEmpty()) {
			logger.error("人行密码表为空并且记录数至少要10条，请补充！");
			throw new RuntimeException("人行密码表为空并且记录数至少要10条");
		} else if (allPwdList.size() < 10) {
			logger.error("人行密码表记录数至少要10条以上，请补充！");
			throw new RuntimeException("人行密码表为空并且记录数至少要10条");
		}

		// 获取userID
		logger.info("获取userID...");
		String userInfoHtml = HttpConnectUtil
				.get(changeByLoginUrl(simuLoginParam.getLoginUrl(), this.processUrl(getCurrUserInfoUrl)), null, cookie);
		logger.debug(userInfoHtml);

		Document userInfoDoc = Jsoup.parse(userInfoHtml);
		Element userID = null != userInfoDoc ? userInfoDoc.getElementById("userID") : null;

		if (StringUtils.isBlank(userInfoHtml) || null == userID || StringUtils.isBlank(userID.val())) {
			logger.error("修改密码失败，获取userID为空");
			throw new RuntimeException("修改密码失败，获取userID为空");
		}
		logger.info("userID：" + userID.val());

		// 获取最近一次使用的密码
		PbocUserPwd currPbocUserPwd = pbocUserPwdRepo.getBySystemPassword(pbocUserInfo.getUserpwd());
		// 获取未使用的密码
		List<PbocUserPwd> pwdList = null;
		// 如果未使用密码不为空则获取大于该ID剩余可用的密码
		if (null != currPbocUserPwd) {
			pwdList = pbocUserPwdRepo.findByGEId(currPbocUserPwd.getId());
		}

		if (null == pwdList) {
			pwdList = new ArrayList<PbocUserPwd>();
		}
		// 添加所有
		pwdList.addAll(allPwdList);

		// 新密码
		PbocUserPwd newPwd = pwdList.get(1);
		logger.info("PW-ID:" + newPwd.getId());
		String newPassword = aesOperator.decrypt(newPwd.getSystemPassword());

		// 设置参数
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("csrfToken", token);
		params.put("userID", userID.val()); // userID
		params.put("oldPassword", aesOperator.decrypt(pbocUserInfo.getUserpwd())); // 旧密码
		params.put("password", newPassword); // 新密码
		params.put("confirmPassword", newPassword); // 确认新密码

		String returnHtml = HttpConnectUtil.post(
				changeByLoginUrl(simuLoginParam.getLoginUrl(), simuLoginParam.getUpdatePasswordUrl()), params, cookie);
		logger.info(returnHtml);

		// 判断页面返回“修改密码成功”(\u4FEE\u6539\u5BC6\u7801\u6210\u529F)的消息
		if (StringUtils.isNotBlank(returnHtml) && StringUtil.unicodeToString(returnHtml)
				.contains("&#x4fee;&#x6539;&#x5bc6;&#x7801;&#x6210;&#x529f;")) {
			logger.info("[" + pbocUserInfo.getUserAcc() + "]修改密码成功");
			// 密码修改成功后拿修改后的密码模拟登陆测试是否成功
			simuLoginParam.setPassWord(newPwd.getSystemPassword());
			simuLoginParam.setEncryptPassword(newPwd.getEncryptPassword());
			return newPwd;
		} else {
			logger.error("判断人行用户密码修改成功方式有误");
			throw new RuntimeException("判断人行用户密码修改成功方式有误");
		}

	}

	/**
	 * 修改人行用户密码，此方法暂不启用
	 * 
	 * @param params
	 * @param cookie
	 */
	@Override
	public String updatePbocUserPassword(PbocUserInfo pbocUserInfo, PbocPwdParam pbocPwdParam) throws Exception {
		PasswordModifPojo passwordModifPojo = new PasswordModifPojo();
		String returnJson = null;
		String loginUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.LOGON_QUERY_DIR);

		String loginPostUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.LOGINURL);

		String tokenUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.TOKENURL);

		String loginSandNumUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(), Const.LOGINSANDNUMURL);

		String updatePasswordUrl = systemConfigUtil.getConfigValue(null, pbocUserInfo.getBrid(),
				Const.UPDATEPASSWORDURL);
		if (StringUtils.isBlank(loginUrl) || StringUtils.isBlank(updatePasswordUrl)) {
			passwordModifPojo.setResultCode(Const.RESULT_CODE_ERROR);
			passwordModifPojo.setResultDesc("企业征信登录地址为空或密码修改请求地址为空，请检查！");
			returnJson = JSONObject.fromObject(passwordModifPojo).toString();
			logger.error("企业征信登录地址为空或密码修改请求地址为空，请检查！");
		} else {

			SimuLoginParam simuLoginParam = new SimuLoginParam(pbocUserInfo);
			simuLoginParam.setLoginUrl(loginUrl);
			simuLoginParam.setLoginPostUrl(loginPostUrl);

			simuLoginParam.setLoginSandNumUrl(loginSandNumUrl);
			simuLoginParam.setTokenUrl(tokenUrl);
			simuLoginParam.setUpdatePasswordUrl(updatePasswordUrl);

			// 获取cookie
			String cookie = this.getCookie(simuLoginParam);
			if (StringUtils.isBlank(cookie)) {
				passwordModifPojo.setResultCode(Const.RESULT_CODE_ERROR);
				passwordModifPojo.setResultDesc("获取cookie失败");
				returnJson = JSONObject.fromObject(passwordModifPojo).toString();
				logger.error("获取cookie失败");
				// throw new RuntimeException("获取cookie失败");
				return returnJson;
			}
			// 获取token
			String token = this.getToken(simuLoginParam, cookie);
			if (StringUtils.isBlank(token)) {
				passwordModifPojo.setResultCode(Const.RESULT_CODE_ERROR);
				passwordModifPojo.setResultDesc("获取token失败");
				returnJson = JSONObject.fromObject(passwordModifPojo).toString();
				logger.error("获取token失败");
				// throw new RuntimeException("获取token失败");
				return returnJson;
			}

			// // 获取所有密码
			// List<PbocUserPwd> allPwdList = pbocUserPwdRepo.getAllBySts();
			//
			// if (null == allPwdList || allPwdList.isEmpty()) {
			// logger.error("人行密码表为空并且记录数至少要10条，请补充！");
			// return null;
			// } else if (allPwdList.size() < 10) {
			// logger.error("人行密码表记录数至少要10条以上，请补充！");
			// return null;
			// }

			// 获取userID
			logger.info("获取userID...");
			String userInfoHtml = HttpConnectUtil.get(
					changeByLoginUrl(simuLoginParam.getLoginUrl(), this.processUrl(getCurrUserInfoUrl)), null, cookie);
			logger.debug(userInfoHtml);

			Document userInfoDoc = Jsoup.parse(userInfoHtml);
			Element userID = null != userInfoDoc ? userInfoDoc.getElementById("userID") : null;

			if (StringUtils.isBlank(userInfoHtml) || null == userID || StringUtils.isBlank(userID.val())) {
				passwordModifPojo.setResultCode(Const.RESULT_CODE_ERROR);
				passwordModifPojo.setResultDesc("修改密码失败，获取userID为空");
				returnJson = JSONObject.fromObject(passwordModifPojo).toString();
				logger.error("修改密码失败，获取userID为空");
				// throw new RuntimeException("修改密码失败，获取userID为空");
			} else {
				logger.info("userID：" + userID.val());

				// // 获取最近一次使用的密码
				// PbocUserPwd currPbocUserPwd =
				// pbocUserPwdRepo.getBySystemPassword(pbocUserInfo.getUserpwd());
				// // 获取未使用的密码
				// List<PbocUserPwd> pwdList = null;
				// // 如果未使用密码不为空则获取大于该ID剩余可用的密码
				// if (null != currPbocUserPwd)
				// pwdList =
				// pbocUserPwdRepo.findByGEId(currPbocUserPwd.getId());
				//
				// if (null == pwdList)
				// pwdList = new ArrayList<PbocUserPwd>();
				// // 添加所有
				// pwdList.addAll(allPwdList);

				// 新密码
				// PbocUserPwd newPwd = pwdList.get(1);
				// logger.info("PW-ID:" + newPwd.getId());
				// String newPassword =
				// AESOperator.getInstance().decrypt(newPwd.getSystemPassword());

				// 设置参数
				Map<String, Object> params = new HashMap<String, Object>();
				params.put("csrfToken", token);
				params.put("userID", userID.val()); // userID
				params.put("oldPassword", aesOperator.decrypt(pbocUserInfo.getUserpwd())); // 旧密码
				params.put("password", pbocPwdParam.getNewPwd()); // 新密码
				params.put("confirmPassword", pbocPwdParam.getNewPwd()); // 确认新密码

				String returnHtml = HttpConnectUtil.post(
						changeByLoginUrl(simuLoginParam.getLoginUrl(), simuLoginParam.getUpdatePasswordUrl()), params,
						cookie);
				logger.info(returnHtml);

				// 判断页面返回“修改密码成功”(\u4FEE\u6539\u5BC6\u7801\u6210\u529F)的消息
				if (StringUtils.isNotBlank(returnHtml) && StringUtil.unicodeToString(returnHtml).contains("修改密码成功")) {
					logger.info("[" + pbocUserInfo.getUserAcc() + "]修改密码成功");
					// 密码修改成功后拿修改后的密码模拟登陆测试是否成功
					simuLoginParam.setEncryptPassword(aesOperator.encrypt(pbocPwdParam.getNewPwd()));
					if (isRestLogic(simuLoginParam)) {
						passwordModifPojo.setResultCode(Const.RESULT_CODE_SUCCESS);
						returnJson = JSONObject.fromObject(passwordModifPojo).toString();
					} else {
						passwordModifPojo.setResultCode(Const.RESULT_CODE_ERROR);
						passwordModifPojo.setResultDesc("修改密码成功后，再次登录测试失败");
						returnJson = JSONObject.fromObject(passwordModifPojo).toString();
						logger.error("修改密码成功后，再次登录测试失败");
					}
				} else {
					passwordModifPojo.setResultCode(Const.RESULT_CODE_ERROR);
					passwordModifPojo.setResultDesc("修改密码失败");
					returnJson = JSONObject.fromObject(passwordModifPojo).toString();
					logger.error("修改密码失败");
					// throw new RuntimeException("修改密码失败");
				}
			}
		}
		return returnJson;
	}

	/**
	 * 处理URL请求，根据参数设置为测试或生产环境
	 * 
	 * @param url
	 * @return
	 */
	private String processUrl(String url) {
		return url.replace("{environment}", this.pbcEnvironment);
	}

	/**
	 * 人行密码修改成功后拿修改后的密码模拟登陆测试是否成功
	 * 
	 * @param simuLoginParam
	 * @return
	 * @throws Exception
	 */
	private boolean isRestLogic(SimuLoginParam simuLoginParam) throws Exception {
		// 获取cookie
		String cookie = this.getCookie(simuLoginParam);
		if (StringUtils.isBlank(cookie)) {
			logger.error("密码更新后测试登陆,获取cookie失败");
			throw new RuntimeException("密码更新后测试登陆,获取cookie失败");
		}
		// 获取token
		String token = this.getToken(simuLoginParam, cookie);
		if (StringUtils.isBlank(token)) {
			logger.error("密码更新后测试登陆,获取token失败");
			throw new RuntimeException("密码更新后测试登陆,获取token失败");
		} else {
			return true;
		}
	}
}
